package ioc.config;

import ioc.bean.Constructor;
import ioc.bean.People;
import ioc.ssm.BookDao;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

/**
 * 自动装配：Spring利用依赖注入（DI），完成对IOC容器中中各个组件的依赖关系赋值；
 *
 * @Autowired Spring定义的规范
 * 1）、默认优先按照类型去容器中找对应的组件，找到就赋值：applicationContext.getBean(BookDao.class)；
 * 2）、如果找到多个相同类型的组件，再将属性的名称作为组件的id去容器中查找：applicationContext.getBean("bookDao")；
 * 3）、@Qualifier("bookDao")：使用@Qualifier指定需要装配的组件的id，而不是使用属性名；
 * 4）、自动装配默认一定要将属性赋值好，没有就会报错，可以使用@Autowired(required=false);
 * 5）、@Primary：在Bean上使用，让Spring进行自动装配的时候，默认使用首选的bean，也可以继续使用@Qualifier指定需要装配的bean的名字；
 * <p>
 * AutowiredAnnotationBeanPostProcessor:解析完成自动装配功能；
 * <p>
 * 在构造器，参数，方法，属性上的使用；都是从容器中获取参数组件的值
 * 1）、[标注在方法位置]或者 @Bean + 方法参数：参数从容器中获取，默认不写 @Autowired 效果是一样的，都能自动装配；
 * 2）、[标在构造器上]：如果组件只有一个有参构造器，这个有参构造器的 @Autowired 可以省略，参数位置的组件还是可以自动从容器中获取
 * 3）、放在参数位置：
 */
@Configuration
@ComponentScan({"ioc"})
public class AutowiredConifg {

    @Primary
    @Bean("bookDao2")
    public BookDao bookDao() {
        BookDao bookDao = new BookDao();
        bookDao.setLable("2");
        return bookDao;
    }

    /**
     * @see Bean
     * 标注的方法创建对象的时候，方法参数的值从容器中获取
     */
    @Bean
    public Constructor constructor(People people) {
        Constructor constructor = new Constructor(people);
        constructor.setPeople2(people);
        return constructor;
    }
}